﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Data;
using System.Collections.Specialized;
using System.Data.SqlClient;
using System.Configuration;
using System.Data.OleDb;
using RoadTeam.DAL;
using System.ComponentModel;
using RoadTeam.Enums;


namespace RoadTeam.Model.Base
{
    public class iTableEntityBase
    {
        public iTableEntityBase() { }

        #region 实体类属性相关操作

        /// <summary>
        /// 属性值被改变的属性名列表
        /// </summary>
        public List<string> PropertyChangedList
        {
            get
            {
                List<string> list = new List<string>();
                if (PropertyNames.Length > 0)
                {
                    for (int i = 0; i < changedlist.Length; i++)
                    {
                        if (changedlist[i])
                            list.Add(PropertyNames[i]);
                    }
                }
                return list;
            }
        }

        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <typeparam name="T">值的类型</typeparam>
        /// <param name="propertyName">属性名称</param>
        /// <returns>属性值</returns>
        protected T getProperty<T>(string propertyName)
        {
            this.OnPropertyGeting(propertyName);
            return iEntityBasePub.ChangeType<T>(PropertyList(propertyName));
        }
        /// <summary>
        /// 属性获取事件
        /// </summary>
        public event EventHandler<PropertyGettingEventArgs> PropertyGetting;
        /// <summary>
        /// 获取属性的时候
        /// </summary>
        /// <param name="name"></param>
        protected virtual void OnPropertyGeting(string name)
        {
            if (this.PropertyGetting != null)
            {
                this.PropertyGetting(this, new PropertyGettingEventArgs(name));
            }
        }
        protected internal virtual void SetFieldNames()
        {
            //this.names = names;
        }
        private bool[] changedlist;
        private string[] names;
        /// <summary>
        /// 属性字段名列表
        /// </summary>
        public virtual string[] PropertyNames
        {
            get
            {
                if (names == null)
                {
                    this.SetFieldNames();
                    changedlist = new bool[names.Length];
                }
                return names;
            }
            protected internal set
            {
                names = value;
                changedlist = new bool[names.Length];
            }
        }
        /// <summary>
        /// 获取属性列的值
        /// </summary>
        /// <param name="propertyName">属性字段名称</param>
        /// <returns>属性值</returns>
        public object PropertyList(string propertyName)
        {
            for (int i = 0; i < PropertyNames.Length; i++)
            {
                if (string.Compare(PropertyNames[i], propertyName, true) == 0)
                {
                    return PropertyValues[i];
                }
            }
            return null;
        }
        private object[] values;
        /// <summary>
        /// 属性值列表
        /// </summary>
        public virtual object[] PropertyValues
        {
            get
            {
                if (values == null)
                {
                    values = new object[PropertyNames.Length];
                }
                return values;
            }
            protected internal set { values = value; }
        }


        /// <summary>
        /// 属性改变事件
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;
        /// <summary>
        /// 触发属性改变事件
        /// </summary>
        /// <param name="e">属性改变事件对象</param>
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, e);
            }
        }


        /// <summary>
        /// 设置属性值
        /// </summary>
        /// <param name="propertyName">属性字段名称</param>
        /// <param name="Value">属性值</param>
        protected internal void setProperty(string propertyName, object Value)
        {
            for (int i = 0; i < PropertyNames.Length; i++)
            {
                if (string.Compare(PropertyNames[i], propertyName, true) == 0)
                {
                    PropertyValues[i] = Value;

                    this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
                    changedlist[i] = true;
                    return;
                }
            }
        }

        /// <summary>
        /// 设置属性，如果值是字符类型且设置了最大长度大于0，那么不允许设置大于此长度的字符串
        /// </summary>
        /// <param name="name">字段名称</param>
        /// <param name="Value">值</param>
        /// <param name="maxLength">最大长度</param>
        protected internal void setProperty(string name, string Value, int maxLength)
        {
            string key = string.Format("{0}_{1}", this.TableName, name);
            StringFieldSize[key] = maxLength;

            if (Value != null && maxLength > 0 && Value.Length > maxLength)
                throw new Exception("字段" + name + "的实际长度超出了最大长度" + maxLength);
            else
                setProperty(name, Value);
        }

        protected internal static Dictionary<string, int> StringFieldSize = new Dictionary<string, int>();
        protected internal static int GetStringFieldSize(string tableName, string fieldName)
        {
            string key = string.Format("{0}_{1}", tableName, fieldName);
            if (StringFieldSize.ContainsKey(key))
                return StringFieldSize[key];
            else
                return 255;
        }


        private string _tableName;
        /// <summary>
        /// 实体类对应的数据库表名称
        /// </summary>
        protected internal string TableName
        {
            set { _tableName = value; }
            get
            {
                if (EntityMap == Db_DataType.SqlMap)
                {
                    int at = _tableName.LastIndexOf('.');
                    if (at > 0)
                        return _tableName.Substring(at + 1);
                    else
                        return _tableName;

                }
                return _tableName;
            }
        }

        private Db_DataType _entityMap = Db_DataType.Table;
        /// <summary>
        /// 实体类的映射类型
        /// </summary>
        protected internal Db_DataType EntityMap
        {
            get { return _entityMap; }
            set { _entityMap = value; }
        }


        #endregion

        public static bool InserObjedct(Type T, Object O, List<String> IExcept, String ConStr)
        {
            TableAttribute tableattribute = new TableAttribute();
            ColumnAttribute[] columnattribute;
            iEntityBasePub.GetEntityProperty(T, out tableattribute, out columnattribute);
            NameValueCollection value = iEntityBasePub.GetPropertyValue(O);
            String StrSeek = String.Empty;
            String StrValue = String.Empty;
            foreach (ColumnAttribute col in columnattribute)
            {
                if (IExcept != null && IExcept.Contains(col.ColumnName)) continue;
                if (col.Identity) continue;
                StrSeek += col.ColumnName + ",";
                StrValue += "@" + col.ColumnName + ",";
            }
            String StrCmd = @" INSERT INTO " + tableattribute.TableName + "(" + StrSeek.TrimEnd(',') + ") VALUES" + "(" + StrValue.TrimEnd(',') + ")";
            return DbFactory.CreateInstance().CreateDb().ExecuteNonQuery(StrCmd, CommandType.Text, value, ConStr) > 0;
        }

        public static bool InsertDatatable(Type T, DataTable dt, String ConStr)
        {
            TableAttribute tableattribute = new TableAttribute();
            ColumnAttribute[] columnattribute;
            iEntityBasePub.GetEntityProperty(T, out tableattribute, out columnattribute);

            String SelectColumn = String.Empty;
            List<string> IExcept = new List<string>();
            foreach (ColumnAttribute Col in columnattribute)
            {
                SelectColumn += Col.ColumnName + ",";
                //不插入自增键
                if (Col.Identity) IExcept.Add(Col.ColumnName);
            }
            String StrSelectCmd = @"SELECT TOP 0 " + SelectColumn.TrimEnd(',') + " FROM " + tableattribute.TableName;

            return DbFactory.CreateInstance().CreateDb().InsertDataTable(StrSelectCmd, dt, tableattribute.TableName, IExcept, ConStr) > 0;
        }

        public static DataTable Select(Type T, SqlWhere where, String ConStr)
        {
            TableAttribute TableName;
            ColumnAttribute[] Columns;
            iEntityBasePub.GetEntityProperty(T, out TableName, out  Columns);

            NameValueCollection iCmdParam = new NameValueCollection();
            String iSqlWhere = String.Empty;

            iEntityBasePub.getParmValue(where, where.Info, Columns, ref iCmdParam, ref  iSqlWhere);
            String StrCmd = @"SELECT {0} FROM {1} WHERE 1=1 {2}";
            String SelectColumn = String.IsNullOrEmpty(where.SelectColumn) ? "*" : where.SelectColumn;
            String StrTableName = TableName.TableName;
            StrCmd = String.Format(StrCmd, SelectColumn, StrTableName, iSqlWhere);
            return DbFactory.CreateInstance().CreateDb().ExecuteQuery(StrCmd, CommandType.Text, iCmdParam, ConStr);
        }

        protected static DataTable Select(Type T, QueryPage page, string ConStr)
        {
            //只能支持单表分页
            TableAttribute TableName;
            ColumnAttribute[] Columns;
            iEntityBasePub.GetEntityProperty(T, out TableName, out  Columns);
            String StrCmd = @"SELECT {0} FROM {1} WHERE 1=1 AND {2} Order By {3}";
            String SelectColumn = String.IsNullOrEmpty(page.PageSelctColumn) ? "*" : page.PageSelctColumn;
            StrCmd = String.Format(StrCmd, SelectColumn, TableName.TableName, page.Where.StrWhere, page.OrderByColumn);
            DataTable dt = Select(T, page.Where, String.Empty, ConStr);
            page.AllCount = Convert.ToInt32(dt.Rows[0][0]);
            //拼接分页Sql
            StrCmd = SQLPage.MakeSQLStringByPage(StrCmd, page.Where.StrWhere, page.PageSize, page.CurrentPage, page.AllCount);
            return DbFactory.CreateInstance().CreateDb().ExecuteQuery(StrCmd, CommandType.Text, page.Where.PreWhere, ConStr);
        }

        protected static DataTable Select(Type T, OQLWhere where, String SelectColumn, String ConStr)
        {
            TableAttribute TableName;
            ColumnAttribute[] Columns;
            iEntityBasePub.GetEntityProperty(T, out TableName, out  Columns);
            String StrCmd = @"SELECT {0} FROM {1} WHERE 1=1 AND  {2}";
            SelectColumn = String.IsNullOrEmpty(SelectColumn) ? " Count(*) " : SelectColumn;
            StrCmd = String.Format(StrCmd, SelectColumn, TableName.TableName, where.StrWhere);
            return DbFactory.CreateInstance().CreateDb().ExecuteQuery(StrCmd, CommandType.Text, where.PreWhere, ConStr);
        }

        public static int Delete(Type T, OQLWhere where, String ConStr)
        {
            TableAttribute TableName;
            ColumnAttribute[] Columns;
            iEntityBasePub.GetEntityProperty(T, out TableName, out  Columns);
            String StrCmd = @"DELETE {0} WHERE {1}";
            StrCmd = String.Format(StrCmd, TableName.TableName, where.StrWhere);
            return DbFactory.CreateInstance().CreateDb().ExecuteNonQuery(StrCmd, CommandType.Text, where.PreWhere, ConStr);
        }

        protected static int Update(Type T, object O, string ConStr)
        {
            TableAttribute TableName;
            ColumnAttribute[] Columns;
            iEntityBasePub.GetEntityProperty(T, out TableName, out  Columns);

            iTableEntityBase baseO = (iTableEntityBase)O;
            object ColumnValue = String.Empty;
            Dictionary<string, object> PreWhere = new Dictionary<string, object>();
            int i = 0;
            if (baseO.PropertyChangedList.Count == 0) return 0;

            String StrSet = String.Empty;
            String StrWhere = String.Empty;
            foreach (ColumnAttribute item in Columns)
            {
                ColumnValue = T.GetProperty(item.ColumnName).GetValue(O, null);
                if (item.IsPrimaryKey && ColumnValue == null)
                    throw new Exception("主键没有赋值,不能执行更新语句!");

                if (item.IsPrimaryKey && ColumnValue != null)
                {
                    PreWhere.Add("@" + item.ColumnName + i, ColumnValue);
                    StrWhere += " [" + item.ColumnName + "] = " + "@" + item.ColumnName + i + ",";
                    i++;
                }

                if (!item.IsPrimaryKey && baseO.PropertyChangedList.Contains(item.ColumnName))
                {
                    PreWhere.Add("@" + item.ColumnName + i, ColumnValue);
                    StrSet += " [" + item.ColumnName + "] = " + "@" + item.ColumnName + i + ",";
                    i++;
                }
            }
            String UpdateCmd = @" Update " + TableName.TableName + " SET " + StrSet.TrimEnd(',') + "  WHERE " + StrWhere.TrimEnd(',');
            return DbFactory.CreateInstance().CreateDb().ExecuteNonQuery(UpdateCmd, CommandType.Text, PreWhere, ConStr);
        }


        public static int Update(Type T, DataTable dt, string ConStr)
        {
            TableAttribute TableName;
            ColumnAttribute[] Columns;
            iEntityBasePub.GetEntityProperty(T, out TableName, out  Columns);

            List<string> PrimaryKeyList = new List<string>();
            List<String> UpdateColumn = new List<string>();
            String SelectColumn = String.Empty;
            foreach (ColumnAttribute Col in Columns)
            {

                if (Col.IsPrimaryKey) PrimaryKeyList.Add(Col.ColumnName);

                if (Col.Identity) continue;

                UpdateColumn.Add(Col.ColumnName);

                SelectColumn += Col.ColumnName + ",";
            }
            String StrSelectCmd = @"SELECT TOP 0 " + SelectColumn.TrimEnd(',') + " FROM " + TableName.TableName;

            return DbFactory.CreateInstance().CreateDb().UpdateDataTable(StrSelectCmd, dt, TableName.TableName, PrimaryKeyList, UpdateColumn, ConStr);
        }

      

    }
}




